#ifndef Database_H
#define Database_H
/** include config.h **/
#include "config.h"

#include <map>
#include <string>
#include <vector>
#include <iostream>
#include <cstdio>

/** Boost Header **/
#include <boost/thread/mutex.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>

#include "AbstractQuery.h"

typedef struct{
	String name;
	String type;
} FieldInfo;

typedef struct{
    String database;
    String schema;
	String name;
	String message;
	bool hasGeometry;
	bool hasSRID;
	FieldInfo geometry;
	size_t countRows;
	size_t tableSize;
	std::vector<FieldInfo> fields;
} TableInfo;



class AbstractDatabase{
	public:
        /** Construtor/Destructor **/
		AbstractDatabase(PString host, PString port, PString database, PString username, PString password);
		virtual ~AbstractDatabase();

        /** Error Handling **/
        void error(char* errmsg, char* param, ...);

        /** query and fetch **/
        virtual PQuery select(PString database, PString schema, std::string *table, int option = OPTION_ALL) = 0;

		virtual PQuery query(std::string sqlQuery) = 0;

		virtual PQuery getTableInfoQuery(PString database, PString schema, PString table) = 0;
		virtual PQuery getFieldListQuery(PString database, PString schema, PString table) = 0;
		TableInfo getTableInfoOf(PString database, PString schema, PString table, int option = OPTION_ALL_INFO);

		/** List Databases, Schemata and Tables **/

		virtual PQuery listDatabases() = 0;
		virtual PQuery listSchemata(PString database) = 0;
		virtual PQuery listTables(PString database, PString schemata) = 0;

        virtual void dropTable(PString database, PString schema, PString  table) = 0;

		/** Exists check**/
        virtual bool exists(PString database, PString schema, PString table) = 0;

        /** Connection **/
        virtual bool isConnected(std::string) = 0;

        /** Other **/
        void rename(String oldname, String newname);

        String getDBDriverName();
        String getHost();
        String getPort();
        String getDatabase();
        String getUserName();
        String getPassword();

        String getLastUpdate(PString database, PString schema, PString table);

		/* Query Thread Safe */
		boost::mutex queryLock;
	protected:
		/** Connection Strings **/
		PString dbDriverName;

		PString host;
		PString port;
		PString database;
		PString username;
		PString password;

		boost::mutex::scoped_lock* lockClass;
};

#endif
